<?php
//--------------------------------------------------------------------------------------------------------
    require_once($config['app_dir'] . '/includes/db.class.php');
    require_once($config['app_dir'] . '/includes/date.class.php');
    require_once($config['app_dir'] . '/includes/template.class.php');
    require_once($config['app_dir'] . '/includes/session.class.php');
    require_once($config['app_dir'] . '/includes/number.class.php');
    require_once($config['app_dir'] . '/includes/string.class.php');

    require_once($config['app_dir'] . '/classes/translation.class.php');
    require_once($config['app_dir'] . '/classes/DataLists.class.php');


    //----------------------------------------------------------------------------------------------------

    class objTraderSignalModel {

        public function Insert($values) {
            return true;
        } //Insert

        public function Update($values) {
            return true;
        } //Update

        public function Close($values) {
            return true;
        } //Close

    } //class TraderSignalModel

    //----------------------------------------------------------------------------------------------------

    class TraderFormDataController {

        static public function Extract($values) {
            if( !$values || !is_array($values) ) return false;

            $result = array();  $first = true;
            foreach($values as $key => $value) {
                if( $first ) {
                    $start = strpos($key, '__') + 2;
                    $first = false;
                } //first time only
                $result[substr($key, $start)] = $value;
            } //foreach

            return $result;
        } //Extract

    } //class TraderFormDataController

    //----------------------------------------------------------------------------------------------------

    class VisualEffect {

        static public  function makeShowInputError($Response, $id) {
            $Response->addAssign($id, 'className', 'errHilite');
            $Response->addScript("new Effect.Pulsate('$id', { pulses:7, duration:1.0});");
        } //makeShowInputError

        static public function makeBlinkDivs($Response, $divs) {
            $Response->addScript("new Effect.multiple([$divs], Effect.Pulsate, { pulses:7, duration:1.0});");
        } //makeBlinkDivs

        static public function makeHighlightDivs($Response, $divs) {
            $Response->addScript("new Effect.multiple([$divs], Effect.Highlight, { duration:1.0});");
        } //makeHighlightDivs

    } //VisualEffect

    //----------------------------------------------------------------------------------------------------

    class objTraderUserModel {
            public $clogin = false;
            public $cpassword = false;

            protected $Session = false;

        public function __construct($flag_check_cookies=true) {
          global $config;
            $this->Session = new objSession($config['app_id']);
            if( $flag_check_cookies && !$this->getLogin() ) {
                $this->getCookieLogin();
                $this->getCookiePassword();

                if( $this->clogin && $this->cpassword &&
                    $this->CheckUser($this->clogin, $this->cpassword) )  $this->Session->Put('trader_user', $this->clogin);
            }

        } //constructor

        public function CheckUser($login, $password) {
            return true;
        } //CheckUser

        static public function isLogined() {
          global $config;
            $Session = new objSession($config['app_id']);
            return $Session->get('trader_user');
        } //isLogined

        public function getLogin() {
            return $this->Session->get('trader_user');
        } //getLogin

        public function Login($login, $password, $fCookies=false) {
            if( $this->CheckUser($login, $password) ) {
                $this->Session->Put('trader_user', $login);
                if( $fCookies ) {
                    $this->setCookieLogin($login);
                    $this->setCookiePassword($password);
                } //cookies
            } //user correct
        } //Login

        public function Logout() {
            $this->Session->Clear('trader_user');
            $this->Session->putCookie('traderlogin', false, time() - 60*60*24*140, '/');
            $this->Session->putCookie('traderpassword', false, time() - 60*60*24*140, '/');
        } //Logout

        public function getCookieLogin() {
            if( $this->Session->isExistsCookie('traderlogin') )
                $this->clogin = $this->Session->getCookie('traderlogin');
            return $this->clogin;
        } //getCookieLogin

        public function getCookiePassword() {
            if( $this->Session->isExistsCookie('traderpassword') )
                $this->cpassword = $this->Session->getCookie('traderpassword');
            return $this->cpassword;
        } //getCookiePassword

        public function setCookieLogin($value) {
            $this->Session->putCookie('traderlogin', $value, time() + 60*60*24*14, '/');
        } //setCookieLogin

        public function setCookiePassword($value) {
            $this->Session->putCookie('traderpassword', $value, time() + 60*60*24*14, '/');
        } //setCookiePassword

    } // class TraderUserModel

    //----------------------------------------------------------------------------------------------------

    class objTraderUserController {
        public $template_form_filename = 'trader/_Trader_form_auth.tpl';
        public $prefix = 'divTraderAuthIn';

        protected $User = false;
        protected $Response = false;

        public function __construct(xajaxResponse $nResponse) {
            $this->Response = $nResponse;
            $this->User = new objTraderUserModel();
        } //constructor

        public function ClassName() {
            return  __CLASS__;
        }//ClassName

        public function Show() {
            $this->Response->addAssign($this->prefix, 'innerHTML', $this->RenderForm());
        } //Show

        public function Clear() {
            $this->Response->addAssign($this->prefix, 'innerHTML', '');
        } //Clear

        public function Login($form_values) {
            $values = TraderFormDataController::Extract($form_values);

            $this->Response->addAlert(var_export($values, true));
            if( !array_key_exists('rememmberme', $values) ) $values['rememmberme'] = false;
            if( !$this->Validate($values) ) return false;

            $this->User->Login($values['login'], $values['password'], $values['rememmberme']);

            return true;
        } //Login

        public function Logout() {
            $this->User->Logout();
        } //Logout

        protected function Validate($values) {
            $TranslationMessage = objTranslationMessage::GetInstance();

            $errors = '';
            $lab_id = 'labelTraderAuthInForm__';

            if( empty($values['login']) ) {
                $errors .= '<li>' . "Login can't be empty."/*$TranslationMessage->GetMessage('_trader__errorSignalSize_Decimal')*/ . '</li>';
                VisualEffect::makeShowInputError($this->Response, $lab_id.'login');
            }

            if( empty($values['password']) ) {
                $errors .= '<li>' . "Password can't be empty."/*$TranslationMessage->GetMessage('_trader__errorSignalSize_Decimal')*/ . '</li>';
                VisualEffect::makeShowInputError($this->Response, $lab_id . 'password');
            }

            if( $errors ) {
                $this->Response->addAssign($this->prefix . 'Form_Errors', 'innerHTML', "<ul id=\"errors\" class=\"errors\">$errors</ul>");
                $this->Response->addAssign('errors', 'style.display', 'inline');
                $this->Response->addAssign($this->prefix . '_Form_Errors', 'className', 'errors');
            } //if there are some errors


            return 0==strlen($errors);
        } //Validate

        protected function RenderForm() {
            $tForm = new objTemplate();
            $tForm->Assign('CLogin', $this->User->getCookieLogin());
            $tForm->Assign('CPassword', $this->User->getCookiePassword());
            return $tForm->Fetch($this->template_form_filename);
        } //RenderForm

    } // class TraderUserController

    //----------------------------------------------------------------------------------------------------

    class objTraderForecastsCollectorController {
            private static $instance;
            private $prefix = 'TraderForecasts_';
            protected $Session = false;

        protected function __construct() {
          global $config;
            $this->Session = new objSession($config['app_id']);
        } //constructor

        public static function GetInstance() {
            if (!isset(self::$instance)) {
                $c = __CLASS__;
                self::$instance = new $c;
            }
            return self::$instance;
        } //GetInstance

        public function __clone() {
            throw new Exception('Cant clone singleton');
        } //clone
        //---------------------------------------------------------------------
        public function isEmpty() {
            return !$this->Session->isExists($this->prefix . 'forecasts') || !$this->Session->Get($this->prefix . 'forecasts');
        } //isEmpty

        public  function Lock() {
            $this->Session->Put($this->prefix . 'lock', '1');
        } //Lock

        public function Unlock() {
            $this->Session->Put($this->prefix . 'lock', '0');
        } //Unlock

        public function isLocked() {
            return $this->Session->Get($this->prefix . 'lock');
        } //Unlock

        public function IncCounter() {
            $this->Session->Put($this->prefix . 'count', 1 + $this->getCounter());
        } //IncCounter

        public function getCounter() {
            return intval($this->Session->Get($this->prefix . 'count'));
        } //getCounter

        public function Set($value) {
            $this->Session->Put($this->prefix . 'forecasts', $value);
        } //Set

        public function Get() {
            return $this->Session->Get($this->prefix . 'forecasts');
        } //Get

        public function Clear($name=false) {
            if( !$name ) {
                $this->Session->Put($this->prefix . 'forecasts', false);
            } else {
                $this->Session->Put($this->prefix . $name, false);
            }
        } //Clear

    } //class TraderForecastsCollectorController

    //----------------------------------------------------------------------------------------------------

    class objTraderForecastsModel extends objObject implements iErrorHandler{
            protected $data = false;
            protected $flag_build = false;

            protected $enable_active = true;
            protected $_db = false;
            protected $_sql_querys = false;
            public $select_limit = 0;
            public $select_offset = 0;
            protected $full_mode = false;

            protected $_trade = false;
            protected $_start = false;
            protected $_finish = false;
            protected $_system = false;
            protected $_forecast_id = false;

            protected $_db_param_date = '%Y-%m-%d-%H-%i-%s';
            protected $_db_show_date = '%Y-%m-%d <br> %H:%i:%s';//'%b %e';

            protected $_error_str = array('no error',//0
                                          'Input parameters are empty'//1
                                         );

        public function __construct($forecast_id=false, $trade=false, $start=false, $finish=false, $system=false) {
            $this->_forecast_id = $forecast_id;
            $this->_trade = $trade;
            $this->_start = $start;
            $this->_finish = $finish;
            $this->_system = $system;

            $this->_db = objDataBase::GetInstance();
        } //constructor

        public function __set($name, $value) {

            switch( strtolower($name) ) {
                case 'enable_active' :
                    $this->enable_active = $value;
                    $this->_sqls();
                break;
                //------------------------------------------------------------------------------
                case 'forecastid':
                case 'forecast_id':
                    $this->_forecast_id = intval($value);
                    $this->_sqls();
                break;
                //------------------------------------------------------------------------------
                case 'tradeid':
                case 'trade_id':
                case 'trade':
                    $this->_trade = intval($value);
                    $this->_sqls();
                break;
                //------------------------------------------------------------------------------
                case 'systemid':
                case 'system_id':
                case 'system':
                    $this->_system = intval($value);
                    $this->_sqls();
                break;
                //------------------------------------------------------------------------------
                case 'start':
                    $this->_start = $value;
                    $this->_sqls();
                break;
                //------------------------------------------------------------------------------
                case 'finish':
                    $this->_finish = $value;
                    $this->_sqls();
                break;
            } //switch

        }//setter

        public function __get($name) {

            switch( strtolower($name) ) {
                case 'enable_active' :
                    return $this->enable_active;
                break;
                //------------------------------------------------------------------------------
                case 'forecastid':
                case 'forecast_id':
                    return $this->_forecast_id;
                break;
                //------------------------------------------------------------------------------
                case 'tradeid':
                case 'trade_id':
                case 'trade':
                    return $this->_trade;
                break;
                //------------------------------------------------------------------------------
                case 'systemid':
                case 'system_id':
                case 'system':
                    return $this->_system;
                break;
                //------------------------------------------------------------------------------
                case 'start':
                    return $this->_start;
                break;
                //------------------------------------------------------------------------------
                case 'finish':
                    return $this->_finish;
                break;
            }//switch

        }//getter

        //-------------------------------------------------------------------------------------

        public function ClassName() {
            return  __CLASS__;
        }//ClassName

        public function Dump() {
            echo "ForecastID \n<br>";var_dump($this->_foreacst_id);
            echo "TradeID \n<br>";var_dump($this->_trade);
            echo "Start \n<br>";var_dump($this->_start);
            echo "Finish \n<br>";var_dump($this->_finish);
            echo "System \n<br>";var_dump($this->_system);
            echo "Data \n<br>";var_dump($this->data);
        } //dump

        //-------------------------------------------------------------------------------------

        public function Clear() {
            $this->data = array();

            $this->_forecast_id = false;
            $this->_trade = false;
            $this->_start = false;
            $this->_finish = false;
            $this->_system = false;

            $this->_sqls();
        } //Clear

        public function getData($force=false) {
            if( !$force && $this->flag_build ) return $this->data;
            if( !$this->Prepare() ) return false;
            return $this->data;
        } //getData

        public function getOne($force=false) {
            $this->getData($force);
            return ( $this->flag_build ? $this->data['forecasts'][0] : false);
        } //getOne

        protected function Prepare() {
            $this->flag_build = false;
            $this->_sqls();
            $this->data = $this->_db->handler->getAll($this->_sql_querys['forecast_list']);
            $this->PostPrepare();
            if( $this->data ) $this->flag_build = true;
            return $this->data;
        }//Prepare

        protected function PostPrepare() {
            $total_profit = 0;
            $arr_id = array();

            for($i=0; $i<count($this->data); $i++) {
                $this->data[$i]['no'] = $i;
                $arr_id[] = $this->data[$i]['ForecastID'];
                $this->data[$i]['decimal'] = NumberConvert::decimal($this->data[$i]['PipSize']);;
                $this->data[$i]['SimpleSystemName'] = StringConvert::SubstrTrimL('IntelliForex', $this->data[$i]['SystemName']);
                $total_profit += floatval($this->data[$i]['Profit']);
            } //for

            $this->data['forecasts'] = $this->data;
            $this->data['total_proft'] = $total_profit;
            $this->data['forecasts_id'] = $arr_id;
        } //PostPrepare

        protected function buildSQLWhere() {
            $whereArr = array();
            //-----------------------------------------------------------------------------------
            $whereArr[0] = array();
            if( $this->_forecast_id ) $whereArr[0][] = "f.ForecastID=$this->_forecast_id";
            if( $this->_trade )  $whereArr[0][] = "t.TradeID=$this->_trade";
            if( $this->_system )  $whereArr[0][] = "f.SystemID=$this->_system";
            //-----------------------------------------------------------------------------------
            $whereArr[1] = array();
            if( $this->_start || $this->_finish ) {
                $whereArr[1][] = "f.CloseTime is not null";
                if( $this->_start )
                    $whereArr[1][] = "FROM_UNIXTIME(f.CloseTime,'$this->_db_param_date') >= '$this->_start' ";
                if( $this->_finish )
                    $whereArr[1][] = "FROM_UNIXTIME(f.CloseTime,'$this->_db_param_date') <= '$this->_finish' ";
            } //if set start or finish
            //-----------------------------------------------------------------------------------
            $whereArr[2] = array();
            if( $this->enable_active ) {
                $whereArr[2][] = "f.CloseTime is null";
                if( $this->_start )
                    $whereArr[2][] = "FROM_UNIXTIME(lq.LastCloseTime,'$this->_db_param_date') >= '$this->_start' ";
                if( $this->_finish )
                    $whereArr[2][] = "FROM_UNIXTIME(lq.LastCloseTime,'$this->_db_param_date') <= '$this->_finish' ";
            } //enable active
            //-----------------------------------------------------------------------------------
            for($i=0; $i<count($whereArr); $i++) {
                $whereArr[$i] = implode(' AND ', $whereArr[$i]);
                if( $whereArr[$i] ) $whereArr[$i] = '('. $whereArr[$i] .')';
            }//for

            $dates = $whereArr[1] . ($whereArr[1] && $whereArr[2] ? ' OR ' : '') . $whereArr[2];
            if( $dates ) $dates ="($dates)";
            return $whereArr[0] . ($whereArr[0] && $dates ? ' AND ' : '') . $dates;
        } //buildSQLWhere

        protected function buildSQLSelect($full=false) {
            $select =
                " f.ForecastID, (f.CloseTime is null) as FlagActive, f.BeginPrice, f.EndPrice, f.StopPrice, f.Size, f.Side, t.PipSize, t.Pair, " .
                " round(f.Size * (1 - 2 * f.Side) * (COALESCE(f.ClosePrice, (1-f.Side)* r.Bid + f.Side*r.Ask, lq.LastClosePrice) - f.BeginPrice) / t.PipSize) as Profit, " .

                $this->_db->handler->Concat('COALESCE(s.ShortName, "")', 'f.ForecastID')." as SignalID, ".
                " s.SystemID, s.ShortName as SystemShortName, s.ChartPeriod, s.TimeFrame, s.ViewPeriod, ".

                " FROM_UNIXTIME(f.BeginTime,'$this->_db_show_date') as OpenTimeF, " .
                " FROM_UNIXTIME(f.CloseTime,'$this->_db_show_date') as CloseTimeF " ;
            if( $full ) {
                $select .=
                   ", f.BeginTime, f.EndTime, f.Color, f.SystemID, ".
                    " f.BeginTime as BeginForecast, ".
                    " COALESCE(f.EndTime, f.CloseTime, f.BeginTime+s.TimeFrame, lq.LastCloseTime) as EndForecast, ".
                    " COALESCE(f.CloseTime,lq.LastCloseTime) as CloseTime,   ".
                    " COALESCE(f.ClosePrice,lq.LastClosePrice) as ClosePrice   ";

            }
            return $select;
        } //buildSQLSelect

        protected function buildSQLOrder() {
            return "(f.CloseTime is null) DESC, COALESCE(f.CloseTime, 0) DESC, f.BeginTime DESC";
        } //buildSQLOrder

        protected function _sqls($aWhere=false) {
            $select = $this->buildSQLSelect($this->full_mode);
            $where = ($aWhere ? $aWhere : $this->buildSQLWhere() );
            $order = $this->buildSQLOrder();
            //------------------------------------------------------------------
            $this->_sql_querys['forecast_list'] =
            " SELECT ". $select .

            " FROM vfa_forecast f ".
                   " LEFT OUTER JOIN fa_trades t ON (f.TradeID = t.TradeID) ".
                   " LEFT OUTER JOIN fa_systems s ON (f.SystemID = s.SystemID)  ".
                   " LEFT OUTER JOIN fa_rates r  ON (f.TradeID=r.TradeID)  ".
                   " LEFT OUTER JOIN ".
                     "(  ".
                      " SELECT ".
                           " ttq.TradeID, ".
                           " ttq.C as LastClosePrice, ".
                           " ttq.TimeStart as LastCloseTime ".
                      " FROM fa_quotes ttq ".
                          " RIGHT OUTER JOIN ( ".
                                " SELECT tq.TradeID, max(tq.TimeStart) as max_quote_time ".
                                " FROM fa_quotes tq ".
                                " GROUP BY tq.TradeID) qq ".
                                " ON (qq.max_quote_time=ttq.TimeStart and qq.TradeID=ttq.TradeID) ".
                    " ) lq ".
                    " ON (f.TradeID = lq.TradeID) ".

            ( $where ? " WHERE $where" : '' ).
            ( $order ? " ORDER BY $order" : '' ).

            ( $this->select_limit ? " LIMIT  $this->select_limit " : '') .
            ( $this->select_offset ? " OFFSET  $this->select_offset " : '')
            ;
        } //sqls

    }//class TraderForecastsShow

    //----------------------------------------------------------------------------------------------------

    class objTraderForecastsController {
            public $template_show_filename = 'trader/_TraderForecasts.tpl';
            public $template_profit_filename = 'trader/_TraderForecasts_Profit.tpl';
            public $template_row_filename = 'trader/_TraderForecasts_Row.tpl';
            public $prefix = 'divTraderOpen';
            public $flag_new_blink = true;

            protected $fields = array('SignalID',
                                      'OpenTimeF',
                                      'Pair',
                                      'Side',
                                      'Size',
                                      'BeginPrice',
                                      'StopPrice',
                                      'EndPrice',
                                      'Profit');

            protected $ufields = array('StopPrice',
                                       'EndPrice',
                                       'Profit');

            protected $ifields = array('Size',
                                       'StopPrice',
                                       'EndPrice',
                                       'Close',
                                       'Update');

            protected $Response = false;
            protected $Model = false;

        public function __construct(xajaxResponse $nResponse, objTraderForecastsModel $nModel) {
            $this->Response = $nResponse;
            $this->Model = $nModel;
        } //constructor

        public function ClassName() {
            return  __CLASS__;
        }//ClassName

        public function isBowserIE() {
            return (false!=strpos($_SERVER['HTTP_USER_AGENT'],'MSIE'));
        } //isBowserIE

        public function Show() {
            $data = $this->Model->getData(true);

            $Collector = objTraderForecastsCollectorController::GetInstance();
            $curr_ids_arr = $data['forecasts_id'];
            $Collector->Set($curr_ids_arr);

            $this->Response->addAssign($this->prefix, 'innerHTML', $this->RenderAll($data));

            $this->makeZebra($curr_ids_arr);
        } //Show

        public function Clear() {
            $this->Response->addAssign($this->prefix, 'innerHTML', '');
        } //Clear

        public function Reload() {

            if( $this->isBowserIE()) {
                $this->Show();
                return true;
            } //dull reload for IE browser

            $data = $this->Model->getData(true);

            $Collector = objTraderForecastsCollectorController::GetInstance();
            $prev_ids_arr = $Collector->Get();
            $curr_ids_arr = $data['forecasts_id'];
            $Collector->Set($curr_ids_arr);

            if( !$prev_ids_arr || empty($prev_ids_arr) || !is_array($prev_ids_arr) )
                $prev_ids_arr = array();
            if( !$curr_ids_arr || empty($curr_ids_arr) || !is_array($curr_ids_arr) )
                $curr_ids_arr = array();

            $upd_ids_arr = array_intersect($prev_ids_arr, $curr_ids_arr);
            $new_ids_arr = array_diff($curr_ids_arr, $upd_ids_arr);
            $del_ids_arr = array_diff($prev_ids_arr, $upd_ids_arr);

            $prev_id = false;
            if( is_array($curr_ids_arr) )
            foreach( $data['forecasts'] as $forecast) {
                $forecast_id = $forecast['ForecastID'];

                if( in_array($forecast_id, $upd_ids_arr) ) { //update row
                    $this->ReloadRow($forecast);
                    if( $this->flag_new_blink ) $this->makeHighlightRow($forecast_id);
                } elseif( in_array($forecast_id, $new_ids_arr) ) { //insert row
                    $this->makeInsertRow($forecast_id, $prev_id);
                    $this->ShowRow($forecast);
                    if( $this->flag_new_blink ) $this->makeBlinkRow($forecast_id);
                }

                $prev_id = $forecast_id;
            } //foreach

            if( is_array($del_ids_arr) )
            foreach( $del_ids_arr as $forecast_id) { //delete old previous rows
                $this->makeDeleteRow($forecast_id);
            }

            $this->makeZebra($curr_ids_arr);

            $this->ReloadTotal($data['total_proft']);
            $this->ReloadValidate();
        } //Reload

        public function Update($values) {
            $result = TraderFormDataController::Extract($values);
            return ($this->Validate($result) ? $result : false);
        } //Update

        protected function ReloadValidate() {
            $this->Response->addAssign($this->prefix . "Table_Errors", 'innerHTML', '');
        } //ReloadValidate

        public function Validate($values) {
            $TranslationMessage = objTranslationMessage::GetInstance();
            $id = 'inpTraderOpenTable_Row_'.$values['forecastid'].'__';

            $errors = '';
            $this->ReloadValidate();

            if( !NumericValidator::isFloat($values['stopprice']) ) {
                $errors .= '<li>' . $TranslationMessage->GetMessage('_trader__errorSignalStopPice_Float') . '</li>';
                $this->Response->addAssign($id . 'stopprice', 'className', 'errHilite');
            }

            if( !NumericValidator::isFloat($values['endprice']) ) {
                $errors .= '<li>' . $TranslationMessage->GetMessage('_trader__errorSignalEndPice_Float') . '</li>';
                $this->Response->addAssign($id . 'endprice', 'className', 'errHilite');
            }

            if( $errors ) {
                $this->Response->addAssign($this->prefix . "Table_Errors", 'innerHTML', "<ul id=\"errors\">$errors</ul>");
                $this->Response->addAssign('errors', 'style.display', 'inline');
                $this->Response->addAssign($this->prefix . "Table_Errors", 'className', 'errors');
            } //if are some errors

            return 0==strlen($errors);
        } //Validate

        //----------------------------------------------------------------------------

        protected function ReloadTotal($total) {
            $this->Response->addAssign($this->prefix . 'Table_TotalProfit', 'innerHTML', $this->RenderProfit($total));
        } //ReloadTotal

        protected function ReloadRow($forecast) {
            $id = $this->RowID($forecast['ForecastID']) . '_value_';

            foreach( $this->ufields as $field ) {
                $this->Response->addAssign($id . strtolower($field), 'innerHTML', $forecast[$field]);
            } //foreach

        } //ReloadRow

        protected function ShowRow($forecast) {
            $this->Response->addAssign($this->RowID($forecast['ForecastID']), 'innerHTML', $this->RenderRow($forecast));
        } //ShowRow

        //----------------------------------------------------------------------------

        protected function RowID($forecast_id) {
            return $this->prefix . ($forecast_id ? 'Table_Row_' . $forecast_id : 'Table_Header');
        } //RowID

        protected function makeZebra($forecasts, $flag_strip=true) {
            $no = 0;
            foreach($forecasts as $forecast) {
                if( !$flag_strip ) {
                    $this->Response->addAssign($this->RowID($forecast), 'className', '');
                } else {
                    $this->Response->addAssign($this->RowID($forecast),
                                               'className',
                                               ( $no%2==1 ? '' : 'darkRow' ));
                }
                $no++;
            } //foreach
        } //makeZebra

        protected function makeDeleteRow($forecast_id) {
            $this->Response->addRemove( $this->RowID($forecast_id) );
        } //makeDeleteRow

        protected function makeInsertRow($forecast_id, $before_id=false) {
            $this->Response->addInsertAfter($this->RowID($before_id) ,
                                            'tr',
                                            $this->RowID($forecast_id) );
        } //makeInsertRow

        protected function makeBlinkRow($forecast_id) {
            VisualEffect::makeBlinkDivs($this->Response, $this->getVisibleDivs($forecast_id));
        } //makeBlinkRow

        protected function makeHighlightRow($forecast_id) {
            $divs = $this->getDivs($forecast_id,'value', array_merge($this->ufields, array('signalid')));
            VisualEffect::makeHighlightDivs($this->Response, $divs);
        } //makeHighlightRow

        protected function getVisibleDivs($forecast_id) {
            return $this->GetDivs($forecast_id);
        } //getVisibleDivs

        protected function getEditableDivs($forecast_id) {
            return $this->GetDivs($forecast_id, 'input');
        } //getEditableDivs

        protected function getDivs($forecast_id, $mode='value', $fields=false) {
            $id = $this->RowID($forecast_id) . '_' . $mode . '_';

            $divs = ''; $first = true;
            if( !$fields ) $fields = ('value'==$mode ? $this->fields : $this->ifields);
            foreach($fields as $field) {
                $divs .= ($first ? '' : ',') . "'" . $id . strtolower($field) . "'";
                if( $first ) $first = false;
            } //foreach

            return $divs;
        } //getDivs

        //----------------------------------------------------------------------------

        protected function RenderAll($data) {
          global $config;
            $Staff = new objStaff($config['app_id']);
            $tShow = new objTemplate();
            $tShow->Assign('ForecastArr', $data['forecasts']);
            $tShow->Assign('TotalProfit', $data['total_proft']);
            $tShow->Assign('Staff', $Staff);
            return $tShow->Fetch($this->template_show_filename);
        } //RenderAll

        protected function RenderRow($forecast) {
            $tRow = new objTemplate();
            $tRow->Assign('Forecast',  $forecast);
            return $tRow->Fetch($this->template_row_filename);
        } //RenderRow

        protected function RenderProfit($profit, $active=true) {
            $tProfit = new objTemplate();
            $tProfit->Assign('Active', $active);
            $tProfit->Assign('Profit', $profit);
            return $tProfit->Fetch($this->template_profit_filename);
        } //RenderProfit

    } //class TraderForecastsController

    //----------------------------------------------------------------------------------------------------

    class objTraderForecastsCountModel extends objTraderForecastsModel implements iErrorHandler{

        public function ClassName() {
            return  __CLASS__;
        }//ClassName

        protected function PostPrepare() {
            $this->data = intval($this->data[0]['total']);
        } //PostPrepare

        public function Render(){
            return false;
        } //Render

        protected function buildSQLSelect() {
            return ' count(*) AS total ';
        } //buildSQLSelect

        protected function buildSQLOrder() {
            return false;
        } //buildSQLOrder

    } //class objTraderForecastsCountModel

    //----------------------------------------------------------------------------------------------------

    class objTraderNewController extends objObject implements iErrorHandler {
            public $template_form_filename = 'trader/_TraderNew_Form.tpl';
            public $prefix = 'divTraderNew';
            public $ifields = array();
            public $system = false;

            protected $Response = false;

        public function __construct(xajaxResponse $nResponse) {
            $this->Response = $nResponse;
        } //constructor

        public function ClassName() {
            return  __CLASS__;
        }//ClassName

        //------------------------------------------------------------------------------------------------

        public function Show() {
            $this->Response->addAssign($this->prefix, 'innerHTML', $this->RenderForm());
            $this->ReloadPairs();
        } //Show

        public function Clear() {
            $this->Response->addAssign($this->prefix, 'innerHTML', '');
        } //Clear

        public function Reload() {
            $this->Response->addScript(" setCheckedRadioValue('inputTraderNew_Form__type', '1');");
            $this->Response->addScript(" enableInputOpenPrice(1);");
            $this->Response->addScript(" setCheckedRadioValue('inputTraderNew_Form__side', '1');");
            $this->Response->addScript(" setInputValue('inputTraderNew_Form__size', '1');");
            $this->Response->addScript(" setInputValue('inputTraderNew_Form__openprice', '');");
            $this->Response->addScript(" setInputValue('inputTraderNew_Form__endprice', '0');");
            $this->Response->addScript(" setInputValue('inputTraderNew_Form__stopprice', '0');");
            $this->ReloadPairs();
            $this->ReloadValidate();
        }  //Reload

        public function ReloadPairs() {
            if( $this->system ) {
                $Pairs = new objPairsSystems();
                $Pairs->system = $this->system;
            } else {
                $Pairs = new objPairs();
            }
            $script .= "document.getElementById('inputTraderNew_Form__pairs').options.length = 0;";
            if( !$Pairs->isEmpty() ) {
                $first = true;
                foreach($Pairs->GetAssocArr() as $pair) {
                    $script .= "var objOption = new Option('" . $pair['Pair'] . "', '" . $pair['TradeID'] . "');";
                    if( $first ) {
                        $script .= " objOption.selected=true;";
                        $first = false;
                    }
                    $script .= "document.getElementById('inputTraderNew_Form__pairs').options.add(objOption);";
                } //for
            } //if
            $this->Response->addScript($script);
        } //ReloadPairs

        public function Save($form_values) {
            $values = $this->ExtractData($form_values);
            return ($this->Validate($values) ? $values : false);
        } //save

        //------------------------------------------------------------------------------------------------
        protected function ExtractData($values) {
            $result = TraderFormDataController::Extract($values);

            if( 2==$result['type'] ) {
                unset($result['openprice']);
            }
            return  $result;
        } //ExtractData

        protected function ReloadValidate() {
            $lab_id = 'labelTraderNew_Form__';

            $this->Response->addAssign($this->prefix . '_Form_Errors', 'innerHTML', '');
            $this->Response->addAssign($lab_id . 'size', 'className', '');
            $this->Response->addAssign($lab_id . 'openprice', 'className', '');
            $this->Response->addAssign($lab_id . 'stopprice', 'className', '');
            $this->Response->addAssign($lab_id . 'endprice', 'className', '');
        }  //ReloadValidate

        protected function Validate($values) {
            $TranslationMessage = objTranslationMessage::GetInstance();

            $errors = '';
            $lab_id = 'labelTraderNew_Form__';

            $this->ReloadValidate();

            if( !NumericValidator::isDecimal($values['size']) ) {
                $errors .= '<li>' . $TranslationMessage->GetMessage('_trader__errorSignalSize_Decimal') . '</li>';
                VisualEffect::makeShowInputError($this->Response, $lab_id.'size');
            } elseif( !NumericValidator::isPositive($values['size']) ) {
                $errors .= '<li>' . $TranslationMessage->GetMessage('_trader__errorSignalSize_Positive') . '</li>';
                VisualEffect::makeShowInputError($this->Response, $lab_id.'size');
            }

            if( array_key_exists('openprice', $values) && !NumericValidator::isFloat($values['openprice']) ) {
                $errors .= '<li>' . $TranslationMessage->GetMessage('_trader__errorSignalOpenPice_Float') . '</li>';
                VisualEffect::makeShowInputError($this->Response, $lab_id.'openprice');
            }

            if( !NumericValidator::isFloat($values['stopprice']) ) {
                $errors .= '<li>' . $TranslationMessage->GetMessage('_trader__errorSignalStopPice_Float') . '</li>';
                VisualEffect::makeShowInputError($this->Response, $lab_id.'stopprice');
            }

            if( !NumericValidator::isFloat($values['endprice']) ) {
                $errors .= '<li>' . $TranslationMessage->GetMessage('_trader__errorSignalEndPice_Float') . '</li>';
                VisualEffect::makeShowInputError($this->Response, $lab_id.'endprice');
            }

            if( $errors ) {
                $this->Response->addAssign($this->prefix . '_Form_Errors', 'innerHTML', "<ul id=\"errors\" class=\"errors\">$errors</ul>");
                $this->Response->addAssign('errors', 'style.display', 'inline');
                $this->Response->addAssign($this->prefix . '_Form_Errors', 'className', 'errors');
            } //if there are some errors


            return 0==strlen($errors);
        } //Validate

        protected function RenderForm() {
            $tForm = new objTemplate();
            return $tForm->Fetch($this->template_form_filename);
        } //RenderForm

    } //class TraderNewController

    //----------------------------------------------------------------------------------------------------

    class objTrader {
            public $template_filename = 'texts/_trader.tpl';

        public function Render() {
          global $config;
            $Staff = new objStaff($config['app_id']);
            $Template = new objTemplate();
            $Template->Assign('formSystemSelector', $this->RenderSystemSelector());
            $Template->Assign('Staff', $Staff);
            return $Template->Fetch($this->template_filename);
        } //Render

        protected function RenderSystemSelector() {
          global $config;
            $Staff = new objStaff($config['app_id']);
            $SystemSelector = new objSystemSelector($Staff->GetSystem(false), true);

            $SystemSelector->action_script = "xajax_reloadTraderOpen(document.getElementById('id_selectsystem_system').value, 0);".
                                             "xajax_reloadTraderNew(document.getElementById('id_selectsystem_system').value, 'pairs');".
                                             "xajax_showTrackRecord(0, document.getElementById('id_selectsystem_system').value);";;

            return $SystemSelector->Render();
        } //RenderSystemSelector

    } //class Trader

    //----------------------------------------------------------------------------------------------------
    // Trader open

    function showTraderOpen($system=false) {
      global $config;
        $Response = new xajaxResponse();

        $Staff = new objStaff($config['app_id']);
        if( false===$system ) $system = $Staff->GetSystem(false);
        $Staff->SetSystem($system);
        if( !$system) $Response->addAssign('id_selectsystem_system', 'value', intval($system));

        $Model = new objTraderForecastsModel();
        $Model->system = $system;

        $Controller = new objTraderForecastsController($Response, $Model);
        $Controller->Show();

        return $Response;
    } //showTraderOpen

    function reloadTraderOpen($system=false, $flag_new_blink=true) {
      global $config;
        $Response = new xajaxResponse();

        $Staff = new objStaff($config['app_id']);
        if( false!==$system ) $Staff->SetSystem($system);

        $Model = new objTraderForecastsModel();
        $Model->system = $Staff->GetSystem(false);

        $Controller = new objTraderForecastsController($Response, $Model);
        $Controller->flag_new_blink = $flag_new_blink;
        $Controller->Reload();

        return $Response;
    } //reloadTraderOpen

    function updateTraderOpen($form_values) {
      global $config;
        $Response = new xajaxResponse();
        $TranslationMessage = objTranslationMessage::GetInstance();
        $Staff = new objStaff($config['app_id']);
        $Model = new objTraderForecastsModel();
        $Model->system = $Staff->GetSystem(false);

        $Controller = new objTraderForecastsController($Response, $Model);
        $values = $Controller->Update($form_values);
        if( $values ) {
            //-----------------------------------------------------------------------------------------------
            // make changes
            $Response->addAlert(var_export($values, true));

            $Signal = new objTraderSignalModel();
            $result = $Signal->Update($values);
            // /make changes
            //-----------------------------------------------------------------------------------------------
            if( $result ) {
                $Response->addAlert($TranslationMessage->GetMessage('_trader__msgSuccessful'));
                $Controller->Reload();
            } // signal modification succesful
        } //if data valid

        return $Response;
    } //updateTraderOpen

    function closeTraderOpen($forecast_id) {
      global $config;
        $Response = new xajaxResponse();
        $TranslationMessage = objTranslationMessage::GetInstance();
        $Staff = new objStaff($config['app_id']);
        $Model = new objTraderForecastsModel();
        $Model->system = $Staff->GetSystem(false);

        $Controller = new objTraderForecastsController($Response, $Model);
        //-----------------------------------------------------------------------------------------------
        // make changes
        $Response->addAlert($forecast_id);

        $Signal = new objTraderSignalModel();
        $result = $Signal->Close($forecast_id);
        // /make changes
        //-----------------------------------------------------------------------------------------------
        if( $result ) {
            $Response->addAlert($TranslationMessage->GetMessage('_trader__msgSuccessful'));
            $Controller->Reload();
        } // signal modification succesful

        return $Response;
    } //closeTraderOpen

    // /Trader open
    //----------------------------------------------------------------------------------------------------
    // Trader new

    function showTraderNew() {
      global $config;
        $Response = new xajaxResponse();
        $Staff = new objStaff($config['app_id']);
        $Controller = new objTraderNewController($Response);
        $Controller->system = $Staff->GetSystem(false);
        $Controller->Show();

        return $Response;
    } //showTraderNew

    function reloadTraderNew($system=false, $mode='all') {
      global $config;
        $Response = new xajaxResponse();
        $Staff = new objStaff($config['app_id']);
        $Controller = new objTraderNewController($Response);
        if( false!==$system ) if( false!==$system ) $Staff->SetSystem($system);
        $Controller->system = $Staff->GetSystem(false);
        if( 'pairs'==$mode )
            $Controller->ReloadPairs();
        else
            $Controller->Reload();

        return $Response;
    } //reloadTraderNew

    function saveTraderNew($form_values) {
      global $config;
        $Response = new xajaxResponse();
        $TranslationMessage = objTranslationMessage::GetInstance();
        $Staff = new objStaff($config['app_id']);
        $Controller = new objTraderNewController($Response);
        $Controller->system = $Staff->GetSystem(false);
        $values = $Controller->Save($form_values);
        if( $values ) {
            // make changes
            $Response->addAlert(var_export($values, true));

            $Signal = new objTraderSignalModel();
            $result = $Signal->Insert($values);
            // /make changes
            if( $result ) {
                $Response->addAlert($TranslationMessage->GetMessage('_trader__msgSuccessful'));
                // reload open forecasts table
                $ForecastsModel = new objTraderForecastsModel();
                $ForecastsModel->system = $Staff->GetSystem(false);
                $ForecastsController = new objTraderForecastsController($Response, $ForecastsModel);
                $ForecastsController->Reload();
                // /reload open forecasts table
            } //if modification successful
        } //if data correct

        return $Response;
    } //saveTraderNew

    // /Trader new
    //----------------------------------------------------------------------------------------------------
    // Trader Auth

    function showTraderAuth($force = true) {
        $Response = new xajaxResponse();
        $Controller = new objTraderUserController($Response);
        if( objTraderUserModel::isLogined() ) {
            $Controller->Clear();
            $Response->addAssign('divTraderAuthOut', 'style.display', 'block');
            $Response->addAssign('divTrader', 'style.display', 'block');
            $Response->addAssign('div_form_systemselector', 'style.display', 'inline');
            $Response->addAssign('divTracksMain', 'style.display', 'block');
        }
        else {
            if( $force ) $Controller->Show();
            $Response->addAssign('divTraderAuthOut', 'style.display', 'none');
            $Response->addAssign('divTrader', 'style.display', 'none');
            $Response->addAssign('divTracksMain', 'style.display', 'none');
            $Response->addAssign('div_form_systemselector', 'style.display', 'none');
        }
        return $Response;
    } // showTraderAuth

    function loginTraderAuth($form_values) {
        $Response = new xajaxResponse();
        $Controller = new objTraderUserController($Response);
        $Controller->Login($form_values);
        $Response->addScriptCall('xajax_showTraderAuth(0);');
        return $Response;
    } // loginTraderAuth

    function logoutTraderAuth() {
        $Response = new xajaxResponse();
        $Controller = new objTraderUserController($Response);
        $Controller->Logout();
        $Response->addScriptCall('xajax_showTraderAuth();');
        return $Response;
    } // loginTraderAuth

    // /Trader Auth
    //----------------------------------------------------------------------------------------------------
    // Trader+TrackRecord

    function toggleTraderTrackRecord() {
      global $config;
        $Session = new objSession($config['app_id']);
        $Response = new xajaxResponse();
        if( $switcher = (bool) ($Session->get('TraderTrackRecordSwitcher')) ) {
            $Response->addAssign('divTracksMain', 'innerHTML', '');
            $Session->put('TraderTrackRecordSwitcher', 0);
        } else {
            $Response->addScriptCall("xajax_showTrackRecord('0');");
            $Session->put('TraderTrackRecordSwitcher', 1);
        }
        
        return $Response;
    } //toggleTraderTrackRecord

    // Trader+TrackRecord
    //----------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------------
?>
